﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using blackhouse.Locations;

namespace blackhouse.BlackApart.Business.Places {
	public class PlaceDistance : IEnumerable<IPlace> {

		#region Fields

		private Location refPoint;
		private DistanceUnit defaultUnit;
		private List<PlaceWithDistance> places = new List<PlaceWithDistance>();

		#endregion

		#region Constructors

		public PlaceDistance(Location referencePoint, DistanceUnit defaultUnit) {
			this.refPoint = referencePoint;
			this.defaultUnit = defaultUnit;
		}

		#endregion

		#region Methods

		public void AddRange(IEnumerable<IPlace> places) {
			this.places.AddRange(places.Select(p => new PlaceWithDistance() { Place = p, Distance = HaversineAlgorithm.CalculateDistance(this.refPoint, p.Location, defaultUnit) }));
		}

		public void SortByDistance() {
			this.places = this.places.OrderBy(p => p.Distance).ToList();
		}

		public IEnumerator<IPlace> GetEnumerator() {
			return this.places.Select(p => p.Place).GetEnumerator();
		}

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
			return this.places.Select(p => p.Place).GetEnumerator();
		}

		public double GetDistance(IPlace place) {
			PlaceWithDistance pwdist = this.places.Where(pwd => pwd.Place.PlaceId == place.PlaceId).FirstOrDefault();
			if (pwdist.Distance == 0)
				return HaversineAlgorithm.CalculateDistance(this.refPoint, place.Location, this.defaultUnit);
			else
				return pwdist.Distance;
		}

		public double GetSpeed(IPlace place, double speedIn_Km_h) {
			double distance = this.GetDistance(place);
			switch (this.defaultUnit) { // Konwersja do kilometrów
				case DistanceUnit.Meters:
					distance = distance / 1000d;
					break;
				case DistanceUnit.Miles:
					distance = distance / 1609.344;
					break;
			}
			double time = distance / speedIn_Km_h;
			time = time * 60; // Konwersja do minut;
			return time;
		}

		public IEnumerable<string> GetDistinctCategories() {
			return this.places.Select(pd => pd.Place.Category).Distinct();
		}

		public IEnumerable<IPlace> GetPlacesByCategory(string category) {
			return this.places.Where(pd => pd.Place.Category == category).Select(pd => pd.Place).Distinct();
		}

		#endregion

	}
}
